package org.cybzacg.convert.enums;

import lombok.Getter;

/**
 * 转换错误类型枚举
 * 定义转换过程中可能出现的错误类型
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Getter
public enum ConversionError {

    /**
     * 空值错误
     */
    NULL_VALUE("NULL_VALUE", "空值错误", "源值为null且目标类型不允许null"),

    /**
     * 类型不匹配错误
     */
    TYPE_MISMATCH("TYPE_MISMATCH", "类型不匹配", "源类型与目标类型不兼容"),

    /**
     * 格式错误
     */
    FORMAT_ERROR("FORMAT_ERROR", "格式错误", "源值格式不符合目标类型要求"),

    /**
     * 数值溢出错误
     */
    NUMBER_OVERFLOW("NUMBER_OVERFLOW", "数值溢出", "数值超出目标类型的表示范围"),

    /**
     * 精度丢失错误
     */
    PRECISION_LOSS("PRECISION_LOSS", "精度丢失", "转换过程中丢失精度"),

    /**
     * 不支持的转换错误
     */
    UNSUPPORTED_CONVERSION("UNSUPPORTED_CONVERSION", "不支持的转换", "不支持从源类型到目标类型的转换"),

    /**
     * 实例化错误
     */
    INSTANTIATION_ERROR("INSTANTIATION_ERROR", "实例化错误", "无法创建目标类型的实例"),

    /**
     * 字段访问错误
     */
    FIELD_ACCESS_ERROR("FIELD_ACCESS_ERROR", "字段访问错误", "无法访问对象的字段"),

    /**
     * 方法调用错误
     */
    METHOD_INVOCATION_ERROR("METHOD_INVOCATION_ERROR", "方法调用错误", "无法调用对象的方法"),

    /**
     * 依赖缺失错误
     */
    DEPENDENCY_MISSING("DEPENDENCY_MISSING", "依赖缺失", "缺少转换所需的依赖"),

    /**
     * 配置错误
     */
    CONFIGURATION_ERROR("CONFIGURATION_ERROR", "配置错误", "转换器配置不正确"),

    /**
     * 缓存错误
     */
    CACHE_ERROR("CACHE_ERROR", "缓存错误", "转换缓存访问失败"),

    /**
     * 并发错误
     */
    CONCURRENCY_ERROR("CONCURRENCY_ERROR", "并发错误", "并发访问导致的错误"),

    /**
     * 资源不足错误
     */
    RESOURCE_EXHAUSTED("RESOURCE_EXHAUSTED", "资源不足", "内存或其他资源不足"),

    /**
     * 超时错误
     */
    TIMEOUT_ERROR("TIMEOUT_ERROR", "超时错误", "转换操作超时"),

    /**
     * 转换失败错误
     */
    CONVERSION_FAILED("CONVERSION_FAILED", "转换失败", "转换过程中发生未知失败"),

    /**
     * 未知错误
     */
    UNKNOWN_ERROR("UNKNOWN_ERROR", "未知错误", "未知的转换错误");

    private final String code;
    private final String name;
    private final String description;

    ConversionError(String code, String name, String description) {
        this.code = code;
        this.name = name;
        this.description = description;
    }

    /**
     * 根据代码获取错误类型
     *
     * @param code 错误代码
     * @return 错误类型
     */
    public static ConversionError fromCode(String code) {
        if (code == null) {
            return UNKNOWN_ERROR;
        }

        for (ConversionError error : values()) {
            if (error.getCode().equalsIgnoreCase(code) ||
                error.name().equalsIgnoreCase(code)) {
                return error;
            }
        }

        return UNKNOWN_ERROR;
    }

    /**
     * 根据异常类型获取错误类型
     *
     * @param exception 异常类型
     * @return 错误类型
     */
    public static ConversionError fromException(Throwable exception) {
        if (exception == null) {
            return UNKNOWN_ERROR;
        }

        String exceptionName = exception.getClass().getSimpleName();

        // 根据异常类型映射到错误类型
        if (exception instanceof NullPointerException) {
            return NULL_VALUE;
        } else if (exception instanceof ClassCastException) {
            return TYPE_MISMATCH;
        } else if (exception instanceof NumberFormatException) {
            return FORMAT_ERROR;
        } else if (exception instanceof ArithmeticException) {
            return NUMBER_OVERFLOW;
        } else if (exception instanceof IllegalAccessException) {
            return FIELD_ACCESS_ERROR;
        } else if (exception instanceof InstantiationException) {
            return INSTANTIATION_ERROR;
        } else if (exception instanceof NoSuchMethodException) {
            return METHOD_INVOCATION_ERROR;
        } else if (exception instanceof OutOfMemoryError) {
            return RESOURCE_EXHAUSTED;
        } else if (exception instanceof InterruptedException) {
            return TIMEOUT_ERROR;
        }

        return UNKNOWN_ERROR;
    }

    /**
     * 检查是否为严重错误
     *
     * @return 是否为严重错误
     */
    public boolean isSevere() {
        return this == INSTANTIATION_ERROR ||
               this == RESOURCE_EXHAUSTED ||
               this == CONCURRENCY_ERROR ||
               this == CONFIGURATION_ERROR;
    }

    /**
     * 检查是否为可恢复错误
     *
     * @return 是否为可恢复错误
     */
    public boolean isRecoverable() {
        return this == NULL_VALUE ||
               this == FORMAT_ERROR ||
               this == PRECISION_LOSS ||
               this == CACHE_ERROR;
    }

    /**
     * 检查是否为用户错误
     *
     * @return 是否为用户错误
     */
    public boolean isUserError() {
        return this == NULL_VALUE ||
               this == TYPE_MISMATCH ||
               this == FORMAT_ERROR ||
               this == UNSUPPORTED_CONVERSION;
    }

    /**
     * 检查是否为系统错误
     *
     * @return 是否为系统错误
     */
    public boolean isSystemError() {
        return this == INSTANTIATION_ERROR ||
               this == FIELD_ACCESS_ERROR ||
               this == METHOD_INVOCATION_ERROR ||
               this == DEPENDENCY_MISSING ||
               this == CONFIGURATION_ERROR ||
               this == CACHE_ERROR ||
               this == CONCURRENCY_ERROR ||
               this == RESOURCE_EXHAUSTED;
    }

    /**
     * 获取错误消息模板
     *
     * @return 错误消息模板
     */
    public String getMessageTemplate() {
        return switch (this) {
            case NULL_VALUE -> "空值不能转换为%s类型: %s";
            case TYPE_MISMATCH -> "类型不匹配，无法将%s转换为%s";
            case FORMAT_ERROR -> "格式错误，期望格式: %s，实际值: %s";
            case NUMBER_OVERFLOW -> "数值溢出，%s超出%s的表示范围";
            case PRECISION_LOSS -> "精度丢失，从%s转换到%s可能丢失精度";
            case UNSUPPORTED_CONVERSION -> "不支持的转换: %s -> %s";
            case INSTANTIATION_ERROR -> "无法实例化类型: %s";
            case FIELD_ACCESS_ERROR -> "无法访问字段: %s";
            case METHOD_INVOCATION_ERROR -> "无法调用方法: %s";
            case DEPENDENCY_MISSING -> "缺少依赖: %s";
            case CONFIGURATION_ERROR -> "配置错误: %s";
            case CACHE_ERROR -> "缓存访问失败: %s";
            case CONCURRENCY_ERROR -> "并发访问错误: %s";
            case RESOURCE_EXHAUSTED -> "资源不足: %s";
            case TIMEOUT_ERROR -> "操作超时: %s";
            case CONVERSION_FAILED -> "转换失败: %s";
            case UNKNOWN_ERROR -> "未知错误: %s";
        };
    }

    @Override
    public String toString() {
        return String.format("%s (%s) - %s", code, name, description);
    }
}
